package com.qqq.portalservice.user.service.impl;

import com.qqq.adminapi.appuser.domain.dto.UserEditReqDTO;
import com.qqq.adminapi.appuser.domain.vo.AppUserVO;
import com.qqq.adminapi.appuser.feign.AppUserFeignClient;
import com.qqq.commoncore.utils.BeanCopyUtil;
import com.qqq.commoncore.utils.VerifyUtil;
import com.qqq.commondomain.domain.R;
import com.qqq.commondomain.domain.ResultCode;
import com.qqq.commondomain.domain.dto.LoginUserDTO;
import com.qqq.commondomain.domain.dto.TokenDTO;
import com.qqq.commondomain.exception.ServiceException;
import com.qqq.commonmessage.service.CaptchaService;
import com.qqq.commonsecurity.service.TokenService;
import com.qqq.commonsecurity.utils.JwtUtil;
import com.qqq.commonsecurity.utils.SecurityUtil;
import com.qqq.portalservice.user.domain.dto.CodeLoginDTO;
import com.qqq.portalservice.user.domain.dto.LoginDTO;
import com.qqq.portalservice.user.domain.dto.UserDTO;
import com.qqq.portalservice.user.domain.dto.WechatLoginDTO;
import com.qqq.portalservice.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 门户用户服务实现类
 */
@Component
@Slf4j
public class UserServiceImpl implements IUserService {

    @Autowired
    private AppUserFeignClient appUserFeignClient;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private CaptchaService captchaService;

    /**
     * 登录
     *
     * @param loginDTO 登录DTO
     * @return token信息
     */
    @Override
    public TokenDTO login(LoginDTO loginDTO) {
        // LoginUserDTO 结构为了维护登录用户⽣命周期
        // 因此登录完成会设置用户信息、token、⽣命周期等属性
        LoginUserDTO loginUserDTO = new LoginUserDTO();
        // 类型检查和类型转换，Java 14及以上版本中的模式匹配特性
        if (loginDTO instanceof WechatLoginDTO wechatLoginDTO) {
            // 处理微信登录逻辑
            loginByWechat(wechatLoginDTO, loginUserDTO);
        } else if (loginDTO instanceof CodeLoginDTO codeLoginDTO) {
            loginByCode(codeLoginDTO, loginUserDTO);
        } else {
            throw new ServiceException("无效的登录方式！", ResultCode.INVALID_PARA.getCode());
        }
        // 该方法会设置用户token、⽣命周期，并返回 Token
        loginUserDTO.setUserFrom("app");
        return tokenService.createToken(loginUserDTO);
    }

    /**
     * 验证码登录处理逻辑
     *
     * @param codeLoginDTO 验证码登录DTO
     * @param loginUserDTO 用户信息上下文DTO
     */
    private void loginByCode(CodeLoginDTO codeLoginDTO, LoginUserDTO loginUserDTO) {
        // 校验手机号
        if (!VerifyUtil.checkPhone(codeLoginDTO.getPhone())) {
            throw new ServiceException("手机号格式错误", ResultCode.INVALID_PARA.getCode());
        }
        // 执行远程调用
        AppUserVO appUserVO;

        R<AppUserVO> result = appUserFeignClient.findByPhone(codeLoginDTO.getPhone());
        // 查不到人的处理逻辑
        if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() || result.getData() == null) {
            appUserVO = register(codeLoginDTO);
        } else {
            appUserVO = result.getData();
        }

        // 校验验证码
        String cacheCode = captchaService.getCode(codeLoginDTO.getPhone());
        if (cacheCode == null) {
            throw new ServiceException("验证码无效", ResultCode.INVALID_PARA.getCode());
        }
        // 校验验证码通过
        captchaService.deleteCode(codeLoginDTO.getPhone());
        // 设置登录信息
        loginUserDTO.setUserId(appUserVO.getUserId());
        loginUserDTO.setUserName(appUserVO.getNickName());
    }

    /**
     * 发送手机验证码
     *
     * @param phone 手机号
     * @return 验证码
     */
    @Override
    public String sendCode(String phone) {
        if (!VerifyUtil.checkPhone(phone)) {
            throw new ServiceException("手机号格式错误",
                    ResultCode.INVALID_PARA.getCode());
        }
        return captchaService.sendCode(phone);
    }

    /**
     * 修改用户信息
     *
     * @param userEditReqDTO 用户编辑DTO
     * @return void
     */
    @Override
    public void edit(UserEditReqDTO userEditReqDTO) {
        R<Void> result = appUserFeignClient.edit(userEditReqDTO);
        if (null == result || result.getCode() != ResultCode.SUCCESS.getCode()) {
            throw new ServiceException("修改用户失败！");
        }
    }

    /**
     * 处理微信登录逻辑
     *
     * @param wechatLoginDTO 微信登录DTO
     * @param loginUserDTO   用户生命周期对象
     */
    private void loginByWechat(WechatLoginDTO wechatLoginDTO, LoginUserDTO loginUserDTO) {
        AppUserVO appUserVO;
        // 根据openId进行查询
        R<AppUserVO> result = appUserFeignClient.findByOpenId((wechatLoginDTO.getOpenId()));
        // 对查询结果进行判断
        if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() || result.getData() == null) {
            // 没查到，需要进行注册
            appUserVO = register(wechatLoginDTO);
        } else {
            appUserVO = result.getData();
        }
        // 设置登录信息
        loginUserDTO.setUserId(appUserVO.getUserId());
        loginUserDTO.setUserName(appUserVO.getNickName());
    }

    /**
     * 根据入参来注册
     *
     * @param loginDTO 用户生命周期信息
     * @return 用户VO
     */
    private AppUserVO register(LoginDTO loginDTO) {
        R<AppUserVO> result = null;
        // 针对入参进行逻辑分发
        if (loginDTO instanceof WechatLoginDTO wechatLoginDTO) {
            // 处理微信注册逻辑
            result = appUserFeignClient.registerByOpenId(wechatLoginDTO.getOpenId());
            if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() || result.getData() == null) {
                log.error("用户注册失败！{}", wechatLoginDTO.getOpenId());
            }
        } else if (loginDTO instanceof CodeLoginDTO codeLoginDTO) {
            // 处理手机号注册逻辑
            result = appUserFeignClient.registerByPhone(codeLoginDTO.getPhone());
            if (result == null || result.getCode() != ResultCode.SUCCESS.getCode() || result.getData() == null) {
                log.error("用户注册失败！{}", codeLoginDTO.getPhone());
            }
        }
        return result == null ? null : result.getData();
    }


    /**
     * 获取用户登录信息
     *
     * @return 用户信息
     */
    @Override
    public UserDTO getLoginUser() {
        // 获取用户登录信息
        LoginUserDTO loginUserDTO = tokenService.getLoginUser();
        if (null == loginUserDTO) {
            throw new ServiceException("用户token有误！",
                    ResultCode.INVALID_PARA.getCode());
        }
        // 获取用户信息
        R<AppUserVO> result =
                appUserFeignClient.findById(loginUserDTO.getUserId());
        if (null == result
                || result.getCode() != ResultCode.SUCCESS.getCode()
                || null == result.getData()) {
            throw new ServiceException("查询用户失败！",
                    ResultCode.ERROR.getCode());
        }
        AppUserVO appUserVO = result.getData();
        UserDTO userDTO = new UserDTO();
        BeanCopyUtil.copyProperties(loginUserDTO, userDTO);
        BeanCopyUtil.copyProperties(result.getData(), userDTO);
        return userDTO;
    }


    /**
     * 退出登录
     */
    @Override
    public void logout() {
        String token = SecurityUtil.getToken();
        if (StringUtils.isEmpty(token)) {
            return;
        }
        String username = JwtUtil.getUserName(token);
        String userId = JwtUtil.getUserId(token);
        log.info("{}退出了，用户id:{}", username, userId);
        // 删除用户缓存记录
        tokenService.delLoginUser(token);
    }   
}
